package com.ruoyi.system.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

public class DateUtil {

    private static final String DATE_FORMAT_PATTERN_YMD = "yyyy-MM-dd";
    private static final String DATE_FORMAT_PATTERN_YMD_HM = "yyyy-MM-dd HH:mm";

    /**
     * 时间戳转字符串
     *
     * @param timestamp     时间戳
     * @param isPreciseTime 是否包含时分
     * @return 格式化的日期字符串
     */
    public static String long2Str(long timestamp, boolean isPreciseTime) {
        return long2Str(timestamp, getFormatPattern(isPreciseTime));
    }

    private static String long2Str(long timestamp, String pattern) {
        return new SimpleDateFormat(pattern, Locale.CHINA).format(new Date(timestamp));
    }

    /**
     * 字符串转时间戳
     *
     * @param dateStr       日期字符串
     * @param isPreciseTime 是否包含时分
     * @return 时间戳
     */
    public static long str2Long(String dateStr, boolean isPreciseTime) {
        return str2Long(dateStr, getFormatPattern(isPreciseTime));
    }

    private static long str2Long(String dateStr, String pattern) {
        try {
            return new SimpleDateFormat(pattern, Locale.CHINA).parse(dateStr).getTime();
        } catch (Throwable ignored) {
        }
        return 0;
    }

    private static String getFormatPattern(boolean showSpecificTime) {
        if (showSpecificTime) {
            return DATE_FORMAT_PATTERN_YMD_HM;
        } else {
            return DATE_FORMAT_PATTERN_YMD;
        }
    }

    /**
     * 将日期转成字符串
     *
     * @param dt
     * @param format
     * @return
     */
    public static String Date2String(Date dt, String format) {
        SimpleDateFormat sf = new SimpleDateFormat(format);
        return sf.format(dt);
    }

    /**
     * 将字符串转成日期
     *
     * @param sdate
     * @param format
     * @return
     */
    public static Date String2Date(String sdate, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date date = new Date();
        try {
            date = sdf.parse(sdate);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 前端传后台的时间格式（如：2019-05-01T16:00:00.000Z）转换成0000-00-00 00:00:00格式
     * @param oldDate
     * @return
     */
    public static String dealDateFormat(String oldDate) {
        Date date1 = null;
        DateFormat df2 = null;
        try {
            oldDate= oldDate.replace("Z", " UTC");
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS Z");
            Date date = df.parse(oldDate);
            SimpleDateFormat df1 = new SimpleDateFormat ("EEE MMM dd HH:mm:ss Z yyyy", Locale.UK);
            date1 = df1.parse(date.toString());
            df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        } catch (ParseException e) {

            e.printStackTrace();
        }
        return df2.format(date1);
    }

    /**
     * 在日期上加1天
     *
     * @param date
     * @param day
     * @return
     */
    public static Date dateAddDay(Date date, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, day);
        return calendar.getTime();
    }


    public static Date dateAdd(Date date, int v, int calendartype) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(calendartype, v);
        return calendar.getTime();
    }

    /**
     * 截掉日期后面的时分秒，将时分秒设为0
     *
     * @param dt
     * @return
     */
    public static Date dateTime2date(Date dt) {
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        String dt_string = sf.format(dt);
        try {
            return sf.parse(dt_string);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 取得指定日期所在周的第一天
     *
     * @param date
     * @return
     */
    public static Date getFirstDayOfWeek(Date date) {
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek()); // Monday
        return c.getTime();
    }

    /**
     * 取得指定日期所在周的最后一天
     *
     * @param date
     * @return
     */
    public static Date getLastDayOfWeek(Date date) {
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek() + 6); // Sunday
        return c.getTime();
    }

    /**
     * 两个日期相减，得到相差天数
     *
     * @param date1
     * @param date2
     * @return
     */
    public static long date_diff(Date date1, Date date2) {
        date1 = dateTime2date(date1);
        date2 = dateTime2date(date2);
        long d1 = date1.getTime();
        long d2 = date2.getTime();
        long d = (d1 - d2) / 1000 / 60 / 60 / 24;
        return d;
    }

    /**
     * 两个日期相减，得到相差的月数
     *
     * @param date1
     * @param date2
     * @return 返回相差的月数
     */
    public static Integer dateDiff(Date date1, Date date2) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date1);
        long time1, time2;
        time1 = date1.getTime();
        time2 = date2.getTime();

        if (time1 > time2) {
            //如果date1小于date2,则两个日期互换，保证date2大于等于date1
            date2.setTime(time1);
            date1.setTime(time2);
        }
        int year1, year2, month1, month2, year, month;

        //获取日期的年、月
        year1 = calendar.get(Calendar.YEAR);
        month1 = calendar.get(Calendar.MONTH);
        calendar.setTime(date2);
        year2 = calendar.get(Calendar.YEAR);
        month2 = calendar.get(Calendar.MONTH);

        //计算两个日期相差几年几月，这里忽略具体几号
        if (year1 == year2) {
            //如果年份相同只要计算月份就行
            year = 0;
            month = month2 - month1;
        } else {
            //年份不同，先用大的年份减去小的年份，在减一，即减法中的高位向低位借一位
            year = year2 - year1 - 1;
            if (month1 <= month2) {
                //大的日期月份也大，不需要借位
                year = year + 1;
                month = month2 - month1;
            } else {
                //大的日期月份小，需要借位
                month = 12 - month1 + month2;
            }
        }

        Integer diff = year * 12 + month;
        return diff;
    }

    /**
     * 两个日期相减，得到相差的月数，忽略日数
     * @param date1
     * @param date2
     * @return
     */
    public static int getMonthNum(Date date1,Date date2) {
        Calendar cal1=Calendar.getInstance();
        cal1.setTime(date1);
        Calendar cal2=Calendar.getInstance();
        cal2.setTime(date2);
        return (cal2.get(1)-cal1.get(1))*12+(cal2.get(2)-cal1.get(2));
    }

    public static Date dateAddMonth(Date date, int inteval) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, inteval);
        return calendar.getTime();
    }

    public static Date dateAddMinute(Date date, int inteval) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, inteval);
        return calendar.getTime();
    }

    /**
     * 获取当前月第一天
     */
    public static String dateMonthFirstDay(Date date) {
        date.setDate(01);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return dateFormat.format(date);
    }

    /**
     * 获取当前年月的最后一天
     * @param yearMonth yyyy-MM (2022-02)
     * @return  2022-02-28
     */
    public static String getLastDayOfMonth(String yearMonth) {
        int year = Integer.parseInt(yearMonth.split("-")[0]);
        int month = Integer.parseInt(yearMonth.split("-")[1]);
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month);
        int lastDay = cal.getMinimum(Calendar.DATE);
        cal.set(Calendar.DAY_OF_MONTH, lastDay - 1);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(cal.getTime());
    }

    /**
     * 两个日期相减，得到xx天xx小时xx分xx秒
     *
     * @param date1
     * @param date2
     * @return
     */
    public static String dateDiff2(Date date1, Date date2) {
        long diff = date1.getTime() - date2.getTime();//这样得到的差值是毫秒级别
        long day = diff / (24 * 60 * 60 * 1000);
        long hour = (diff / (60 * 60 * 1000) - day * 24);
        long min = ((diff / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long s = (diff / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        if (day == 0) {
            return hour + "时" + min + "分" + s + "秒";
        }
        return day + "天" + hour + "时" + min + "分" + s + "秒";
    }

    /**
     * 分换算成天、时、分格式
     *
     * @param min
     * @return
     */
    public static String minConvertDayHourMin(Double min) {
        String html = "0分";
        if (min != null) {
            Double m = (Double) min;
            String format;
            Object[] array;
            Integer days = (int) (m / (60 * 24));
            Integer hours = (int) (m / (60) - days * 24);
            Integer minutes = (int) (m - hours * 60 - days * 24 * 60);
            if (days > 0) {
                format = "%1$,d天%2$,d时%3$,d分";
                array = new Object[]{days, hours, minutes};
            } else if (hours > 0) {
                format = "%1$,d时%2$,d分";
                array = new Object[]{hours, minutes};
            } else {
                format = "%1$,d分";
                array = new Object[]{minutes};
            }
            html = String.format(format, array);
        }
        return html;
    }

    /**
     * 秒换算成天、时、分、秒格式
     *
     * @param mss
     * @return
     */
    public static String secConvertDayHourMinSec(long mss) {
        String DateTimes = null;
        long days = mss / (60 * 60 * 24);
        long hours = (mss % (60 * 60 * 24)) / (60 * 60);
        long minutes = (mss % (60 * 60)) / 60;
        long seconds = mss % 60;
        if (days > 0) {
            DateTimes = days + "天" + hours + "时" + minutes + "分" + seconds + "秒";
        } else if (hours > 0) {
            DateTimes = hours + "时" + minutes + "分" + seconds + "秒";
        } else if (minutes > 0) {
            DateTimes = minutes + "分" + seconds + "秒";
        } else {
            DateTimes = seconds + "秒";
        }
        return DateTimes;
    }

    /**
     * 计算两个时间之间的差值，根据标志的不同而不同
     *
     * @param flag 计算标志，表示按照年/月/日/时/分/秒等计算
     * @return 两个日期之间的差值
     */
    public static int dateDiff(char flag, Date startTime, Date endTime) {
        long millisDiff = endTime.getTime() - startTime.getTime();
        // 以毫秒表示的时间
        long DAY_IN_MILLIS = 24 * 3600 * 1000;
        long HOUR_IN_MILLIS = 3600 * 1000;
        long MINUTE_IN_MILLIS = 60 * 1000;
        long SECOND_IN_MILLIS = 1000;
        if (flag == 'd') {
            return (int) (millisDiff / DAY_IN_MILLIS);
        }
        if (flag == 'h') {
            return (int) (millisDiff / HOUR_IN_MILLIS);
        }
        if (flag == 'm') {
            return (int) (millisDiff / MINUTE_IN_MILLIS);
        }
        if (flag == 's') {
            return (int) (millisDiff / SECOND_IN_MILLIS);
        }
        return 0;
    }

    public static int getDaysOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }
}
